﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpSphinx.Linguist.Acoustic;

namespace SharpSphinx.Linguist.Dictionary
{
    public class Pronunciation
    {
        public static Pronunciation Unknown = new Pronunciation(Unit.Empty_Array, null, null, 1.0f); 



        private Word word;
        private WordClassification wordClassification;
        private Unit[] units;
        private String tag;
        private float mProbability; 



        /// <summary>
        /// Creates a pronunciation
        /// </summary>
        /// <param name="units">represents the pronunciation</param>
        /// <param name="tag">a grammar specific tag</param>
        /// <param name="wordClassification">the classification for this word</param>
        /// <param name="probability">the probability of this pronunciation occurring</param>
        protected Pronunciation(Unit[] units, 
                              String tag, 
                              WordClassification wordClassification,
                              float probability)
        {

            this.wordClassification = wordClassification;
            this.units = units;
            this.tag = tag;
            this.mProbability = probability; 

         }


        /// <summary>
        /// Creates a pronunciation
        /// </summary>
        /// <param name="units">represents the pronunciation</param>
        /// <param name="tag">a grammar specific tag</param>
        /// <param name="wordClassification">the classification for this word</param>
        /// <param name="probability">the probability of this pronunciation occurring</param>
        protected Pronunciation(List<Unit> units, 
                                String tag, 
                                WordClassification wordClassification,
                                float probability)
        {


            Unit[] unitsArray = units.ToArray();
            this.mProbability = probability;
            this.units = unitsArray;
            this.tag = tag;
            this.wordClassification = wordClassification; 
            

        }

        /// <summary>
        /// Creates a pronunciation with defaults
        /// </summary>
        /// <param name="units">represents the pronunciation</param>
        protected Pronunciation(List<Unit> units)
        {
            this.units = units.ToArray();
            this.wordClassification = null;
            this.mProbability = 1.0f;
            this.tag = null; 
            
        }

        /// <summary>
        /// Sets the word this pronunciation represents.
        /// </summary>
        /// <param name="word"></param>
        protected void setWord(Word word)
        {
            if (this.word == null)
            {
                this.word = word;

            }
            else
            {
                throw new Exception("Word Of Pronunciation cannot be set twice."); 

            }
        }


        /// <summary>
        /// Retrieves the word that this Pronunciation object represents.
        /// </summary>
        public Word Word
        {
            get
            {
                return this.word;
            }
        }

        /// <summary>
        ///  Retrieves the word classification for this pronunciation
        /// </summary>
        public WordClassification WordClassification
        {
            get
            {
                return this.wordClassification;
            }
        }

        /// <summary>
        /// Retrieves the units for this pronunciation
        /// </summary>
        public Unit[] Units
        {
            get
            {
                return units;
            }
        }


        /// <summary>
        /// Retrieves the tag associated with the pronunciation or null if there is no tag associated with this
        /// pronunciation. Pronunciations can optionally be tagged to allow applications to distinguish between different
        /// pronunciations.
        /// </summary>
        public String Tag
        {
            get
            {
                return tag;
            }
        }

        /// <summary>
        /// Retrieves the probability for the pronunciation. A word may have multiple pronunciations that are not all equally
        /// probable. All probabilities for particular word sum to 1.0.
        /// </summary>
        public float Probability
        {
            get
            {
                return mProbability; 

            }
        }


        public String Dump
        {
            get
            {
                throw new NotImplementedException("DUMP NOT IMPLEMENTED");
            }

        }

        /// <summary>
        /// Returns a string representation of this Pronunication.
        /// </summary>
        /// <returns>Returns a string representation of this Pronunication.</returns>
        public override string ToString()
        {
            StringBuilder result = new StringBuilder().Append(Word).Append('(');
            foreach (Unit unit in units)
            {
                result.Append(unit).Append(' ');
            }
            result.Append(')');
            return result.ToString();
        }

        /// <summary>
        /// Returns a detailed string representation of this Pronunication.
        /// </summary>
        /// <returns>a string of this Pronunciation</returns>
        public String ToDetailedString()
        {
            StringBuilder result = new StringBuilder().Append(Word).Append('(');
            foreach (Unit unit in units)
            {
                result.Append(unit).Append(' ');
            }

            result.Append("\n Class: ").Append(wordClassification).Append(" Tag: ").Append(tag).Append(" Prob: ").Append(Probability);

            return result.ToString();
        }

    }
}
